using System;

namespace KodeIT.Web
{
    /// <summary>
    /// This class represents the event raised by IIS when it maps a URL to a physical directory. If your HttpFilter should 
    /// be notified for this event, it should subscribe for the <see cref="IFilterEvents.UrlMap"/> event.
    /// </summary>
    /// <remarks>
    /// When the server is about to map the specified URL to a physical path, this event is raised by IIS
    /// and HttpFilters can modify the physical path. When this event occurs it is too late in the server 
    /// processing to use this event to change a URL for a static file into an ISAPI or CGI request, or 
    /// vice versa. If you need to make this change, you must use the <see cref="IFilterEvents.PreProcHeaders"/> 
    /// event and change the url to modify the client request.
    /// </remarks>
    public class UrlMapEvent : ContextEvent
    {
        private NativeString _mappedUrl;
        private NativeString _mappedPath;

        internal UrlMapEvent(NativeContext nativeContext, int urlLength, int pathLength)
            : base(nativeContext)
        {
            NativeGetter getter = new NativeGetter(Populate);
            _mappedUrl = new NativeString(urlLength, getter);
            _mappedPath = new NativeString(pathLength, getter);
        }

        /// <summary>
        /// Gets the URL that is being mapped to a physical path.
        /// </summary>
        public string MappedUrl
        {
            get { return _mappedUrl.Data; }
        }

        /// <summary>
        /// Gets or sets the physical path.
        /// </summary>
        public string MappedPath
        {
            get { return _mappedPath.Data; }
            set
            {
                if (String.IsNullOrEmpty(value))
                {
                    throw new ArgumentNullException("value",
                        "The physical path cannot be null or empty");
                }

                _mappedPath.Data = value;
            }
        }

        private void Populate()
        {
            NativeMethods.GetUrlMap(NativeContext, _mappedUrl, _mappedPath);
        }

        internal override FilterStatus Update()
        {
            if (_mappedPath.Setted)
            {
                NativeMethods.SetUrlMap(NativeContext, MappedPath);
            }
            return base.Update();
        }
    }
}
